// MqttCommandSender.js
import MqttClient from './MqttClient.js';

/**
 * 命令类型枚举
 */
export const CommandType = {
    TEMPERATURE: 'TEMPERATURE',          // 温度命令
    OUT_TEMPERATURE: 'OUT_TEMPERATURE',  // 室外温湿度
    AIR_QUALITY: 'AIR_QUALITY',          // 空气质量检测
    AC_CONTROL: 'AC_CONTROL',            // 空调控制
    LIGHT_CONTROL: 'LIGHT_CONTROL',      // 灯光控制
    HEAT_CONTROL: 'HEAT_CONTROL',        // 加热控制
    DEHUMIDIFY_CONTROL: 'DEHUMIDIFY_CONTROL', // 除湿控制
    ALARM_LIGHT_CONTROL: 'ALARM_LIGHT_CONTROL', // 报警灯控制
    SMOKE_SENSOR: 'SMOKE_SENSOR'         // 烟感控制
}

// 导出单例实例
export default new MqttCommandSender();;

/**
 * MQTT设备命令发送器
 */
class MqttCommandSender {
    constructor() {
        // CRC表
        this.CRC_TABLE = [
            0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
            0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
            0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
            0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
            0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
            0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
            0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
            0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
            0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
            0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
            0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
            0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
            0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
            0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
            0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
            0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
            0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
            0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
            0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
            0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
            0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
            0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
            0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
            0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
            0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
            0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
            0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
            0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
            0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
            0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
            0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
            0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
        ];

        // 预定义命令
        this.COMMANDS = {
            // Modbus命令 (添加F2前缀，计算CRC后发送)
            temperature: "01 03 04 0A 00 02",
            out_warmHumidity: "03 03 00 00 00 02",
            airDetection: "02 03 00 00 00 03",
            hotOpening: "04 05 00 00 FF 00",
            hotOff: "04 05 00 01 FF 00",
            coldOpening: "04 05 00 02 FF 00",
            coldOff: "04 05 00 03 FF 00",

            // 灯光控制 (CC DD格式命令，无需计算CRC)
            lightOn: "CC DD A1 01 00 01 00 01 A4 48 DD CC",
            lightOff: "CC DD A1 01 00 00 00 01 A3 46 DD CC",

            // 加热控制
            heatOn: "CC DD A1 01 00 02 00 02 A6 4C DD CC",
            heatOff: "CC DD A1 01 00 00 00 02 A4 48 DD CC",

            // 除湿控制
            dehumidifyOn: "CC DD A1 01 00 04 00 04 AA 54 DD CC",
            dehumidifyOff: "CC DD A1 01 00 00 00 04 A6 4C DD CC",

            // 报警灯控制
            alarmLightOn: "CC DD A1 01 00 08 00 08 B2 64 DD CC",
            alarmLightOff: "CC DD A1 01 00 00 00 08 AA 54 DD CC",

            // 烟感检测
            smokeSensor: "CC DD C0 01 00 00 0D CE 9C"
        }

        /**
         * 解析温度和湿度数据
         * @param {Uint8Array} data - 数据字节
         * @returns {Object} - 解析后的温湿度数据
         */
        parseTemperatureHumidityData(data)
        {
            // 检查数据长度
            if (data.length < 4) {
                throw new Error('温湿度数据不完整');
            }

            try {
                // 解析温度 (00 BC -> 188 -> 18.8°C)
                const tempRaw = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
                const temperature = tempRaw / 10.0;

                // 解析湿度 (01 A3 -> 419 -> 41.9%)
                const humRaw = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
                const humidity = humRaw / 10.0;

                // 数据有效性检查
                if (temperature < -40 || temperature > 85) {
                    throw new Error(`温度数据超出有效范围: ${temperature}`);
                }

                if (humidity < 0 || humidity > 100) {
                    throw new Error(`湿度数据超出有效范围: ${humidity}`);
                }

                return {
                    temperature: temperature.toFixed(1),
                    humidity: humidity.toFixed(1)
                };
            } catch (e) {
                throw new Error(`温湿度数据解析错误: ${e.message}`);
            }
        }

        /**
         * 解析空气质量数据
         * @param {Uint8Array} data - 数据字节
         * @returns {Object} - 解析后的空气质量数据
         */
        parseAirQualityData(data)
        {
            // 检查数据长度
            if (data.length !== 6) {
                throw new Error(`空气质量数据长度错误: 需要6字节，实际${data.length}字节`);
            }

            try {
                // 解析PM2.5 (第1-2字节)
                const pm25 = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);

                // 解析PM10 (第3-4字节)
                const pm10 = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);

                // 解析PM1.0 (第5-6字节)
                const pm1 = ((data[4] & 0xFF) << 8) | (data[5] & 0xFF);

                // 数据有效性检查
                if (pm25 < 0 || pm25 > 1000) {
                    throw new Error(`PM2.5数据超出有效范围: ${pm25}`);
                }

                if (pm10 < 0 || pm10 > 1000) {
                    throw new Error(`PM10数据超出有效范围: ${pm10}`);
                }

                if (pm1 < 0 || pm1 > 1000) {
                    throw new Error(`PM1.0数据超出有效范围: ${pm1}`);
                }

                return {
                    pm25,
                    pm10,
                    pm1
                };
            } catch (e) {
                throw new Error(`空气质量数据解析错误: ${e.message}`);
            }
        }

        /**
         * 计算CRC校验值
         * @param {Array|Uint8Array} data - 需要计算CRC的字节数组
         * @return {number} - 计算得到的CRC值
         */
        calculateCRC(data)
        {
            let crc = 0xFFFF;
            for (let i = 0; i < data.length; i++) {
                const b = data[i] & 0xFF;
                crc = ((crc >>> 8) ^ this.CRC_TABLE[(crc ^ b) & 0xFF]) & 0xFFFF;
            }
            return crc;
        }

        /**
         * 将数组转换为十六进制字符串
         * @param {Array|Uint8Array} array - 字节数组
         * @returns {string} - 转换后的十六进制字符串，如"A5 00 12"
         */
        arrayToHexString(array)
        {
            return Array.from(array)
                .map(byte => byte.toString(16).padStart(2, '0').toUpperCase())
                .join(' ');
        }
        ;

        // 命令类型映射
        this.COMMAND_TYPES = {
            temperature: CommandType.TEMPERATURE,
            out_warmHumidity: CommandType.OUT_TEMPERATURE,
            airDetection: CommandType.AIR_QUALITY,
            hotOpening: CommandType.AC_CONTROL,
            hotOff: CommandType.AC_CONTROL,
            coldOpening: CommandType.AC_CONTROL,
            coldOff: CommandType.AC_CONTROL,

            lightOn: CommandType.LIGHT_CONTROL,
            lightOff: CommandType.LIGHT_CONTROL,

            heatOn: CommandType.HEAT_CONTROL,
            heatOff: CommandType.HEAT_CONTROL,

            dehumidifyOn: CommandType.DEHUMIDIFY_CONTROL,
            dehumidifyOff: CommandType.DEHUMIDIFY_CONTROL,

            alarmLightOn: CommandType.ALARM_LIGHT_CONTROL,
            alarmLightOff: CommandType.ALARM_LIGHT_CONTROL,

            smokeSensor: CommandType.SMOKE_SENSOR
        };

        // 命令格式类型
        this.COMMAND_FORMATS = {
            temperature: 'MODBUS',
            out_warmHumidity: 'MODBUS',
            airDetection: 'MODBUS',
            hotOpening: 'MODBUS',
            hotOff: 'MODBUS',
            coldOpening: 'MODBUS',
            coldOff: 'MODBUS',

            lightOn: 'FIXED',
            lightOff: 'FIXED',
            heatOn: 'FIXED',
            heatOff: 'FIXED',
            dehumidifyOn: 'FIXED',
            dehumidifyOff: 'FIXED',
            alarmLightOn: 'FIXED',
            alarmLightOff: 'FIXED',
            smokeSensor: 'FIXED'
        };
    }

    /**
     * 发送预定义命令
     * @param {string} commandName - 命令名称
     * @returns {Object} - 包含发送状态和命令类型的对象
     */
    sendCommand(commandName) {
        if (!this.COMMANDS[commandName]) {
            console.error(`未知的命令名称: ${commandName}`);
            return {success: false, message: '未知的命令名称'};
        }

        const commandHex = this.COMMANDS[commandName];
        const commandType = this.COMMAND_TYPES[commandName];
        const commandFormat = this.COMMAND_FORMATS[commandName];

        return this.sendCustomCommand(commandHex, commandType, commandFormat);
    }

    /**
     * 发送自定义命令
     * @param {string} commandHex - 十六进制命令字符串
     * @param {string} commandType - 命令类型
     * @param {string} [format='MODBUS'] - 命令格式，MODBUS或FIXED
     * @returns {Object} - 包含发送状态和命令类型的对象
     */
    sendCustomCommand(commandHex, commandType, format = 'MODBUS') {
        try {
            let hexCommand;
            let originalCommand = commandHex;

            // 根据命令格式处理
            if (format === 'MODBUS') {
                // MODBUS格式：需要添加F2前缀并计算CRC
                // 1. 去除命令中的空格
                const cleanCommand = commandHex.replace(/\s+/g, '');

                // 2. 将十六进制字符串转换为字节数组
                const commandBytes = [];
                for (let i = 0; i < cleanCommand.length; i += 2) {
                    commandBytes.push(parseInt(cleanCommand.substr(i, 2), 16));
                }

                // 3. 计算CRC
                const crc = this.calculateCRC(commandBytes);

                // 4. 构建完整命令，前缀F2 + 命令 + CRC(低字节在前，高字节在后)
                const fullCommand = [
                    0xF2, // 添加前缀F2
                    ...commandBytes,
                    crc & 0xFF,
                    (crc >> 8) & 0xFF
                ];

                // 5. 转换为十六进制字符串
                hexCommand = this.arrayToHexString(fullCommand);
            } else if (format === 'FIXED') {
                // FIXED格式：固定格式命令，已包含校验码，直接发送
                hexCommand = commandHex;
            } else {
                throw new Error(`不支持的命令格式: ${format}`);
            }

            // 发送命令 - 使用MQTT客户端发送
            const success = MqttClient.sendHexData(hexCommand);

            return {
                success: success,
                commandType: commandType,
                format: format,
                originalCommand: originalCommand,
                fullCommand: hexCommand,
                message: success ? '命令发送成功' : '命令发送失败'
            };
        } catch (error) {
            console.error('发送命令异常:', error);
            return {
                success: false,
                commandType: commandType,
                message: `发送命令异常: ${error.message}`
            };
        }
    }

    /**
     * 解析设备返回的数据
     * @param {Uint8Array} data - 接收到的数据
     * @returns {Object|null} - 解析结果，验证失败返回null
     */
    parseResponse(data) {
        try {
            // 检查数据长度
            if (!data || data.length < 3) return null;

            // 检查是否是CCDD格式的命令响应
            if (this.isCCDDResponse(data)) {
                return this.parseCCDDResponse(data);
            }

            // 检查是否是烟感响应 (EE FF开头)
            if (this.isSmokeSensorResponse(data)) {
                return this.parseSmokeSensorResponse(data);
            }

            // 检查是否是简单的"OK!"响应 (4F 4B 21)
            if (this.isOKResponse(data)) {
                return this.parseOKResponse(data);
            }

            // 否则按Modbus格式解析
            return this.parseModbusResponse(data);
        } catch (error) {
            console.error('解析响应数据异常:', error);
            return null;
        }
    }

    /**
     * 检查是否是CCDD格式的响应
     * @param {Uint8Array} data - 响应数据
     * @returns {boolean} - 是否是CCDD格式
     */
    isCCDDResponse(data) {
        return data.length >= 4 && data[0] === 0xCC && data[1] === 0xDD;
    }

    /**
     * 检查是否是烟感响应
     * @param {Uint8Array} data - 响应数据
     * @returns {boolean} - 是否是烟感响应
     */
    isSmokeSensorResponse(data) {
        return data.length >= 4 && data[0] === 0xEE && data[1] === 0xFF;
    }

    /**
     * 检查是否是"OK!"响应
     * @param {Uint8Array} data - 响应数据
     * @returns {boolean} - 是否是"OK!"响应
     */
    isOKResponse(data) {
        return data.length === 3 && data[0] === 0x4F && data[1] === 0x4B && data[2] === 0x21;
    }

    /**
     * 解析CCDD格式的响应
     * @param {Uint8Array} data - 响应数据
     * @returns {Object} - 解析结果
     */
    parseCCDDResponse(data) {
        // 这里需要根据具体协议来解析CCDD格式的响应
        // 通常格式为: CC DD 命令 设备地址 数据... 校验码 DD CC
        const command = data[2];
        const address = data[3];
        const dataBytes = data.slice(4, data.length - 4);

        return {
            format: 'CCDD',
            command: command,
            address: address,
            dataBytes: Array.from(dataBytes),
            rawData: Array.from(data)
        };
    }

    /**
     * 解析烟感响应
     * @param {Uint8Array} data - 响应数据
     * @returns {Object} - 解析结果
     */
    parseSmokeSensorResponse(data) {
        // 烟感响应格式: EE FF C0 01 00 state 0D xx xx
        // state: 00=无报警, 01=有报警
        if (data.length < 9) return null;

        const command = data[2]; // 通常是C0
        const address = data[3]; // 通常是01
        const alarmState = data[5]; // 0=无报警, 1=有报警

        return {
            format: 'SMOKE_SENSOR',
            commandType: CommandType.SMOKE_SENSOR,
            command: command,
            address: address,
            hasAlarm: alarmState === 0x01,
            rawData: Array.from(data),
            parsedData: {
                hasAlarm: alarmState === 0x01,
                status: alarmState === 0x01 ? '有报警' : '无报警'
            }
        };
    }

    /**
     * 解析"OK!"响应
     * @param {Uint8Array} data - 响应数据
     * @returns {Object} - 解析结果
     */
    parseOKResponse(data) {
        // "OK!"响应通常表示控制命令执行成功
        return {
            format: 'OK_RESPONSE',
            success: true,
            message: 'OK!',
            rawData: Array.from(data)
        };
    }

    /**
     * 解析Modbus格式的响应
     * @param {Uint8Array} data - 响应数据
     * @returns {Object|null} - 解析结果，验证失败返回null
     */
    parseModbusResponse(data) {
        // 检查数据长度
        if (data.length < 5) return null; // 至少需要: 地址(1) + 功能码(1) + 字节数(1) + CRC(2)

        const address = data[0];       // 地址码
        const functionCode = data[1];  // 功能码
        const byteCount = data[2];     // 有效字节数

        // 验证数据长度
        if (data.length < 3 + byteCount + 2) {
            console.error('数据长度不足');
            return null;
        }

        // 提取有效数据部分
        const payload = data.slice(3, 3 + byteCount);

        // 提取CRC (低字节在前，高字节在后)
        const receivedCrc = (data[3 + byteCount + 1] << 8) | data[3 + byteCount];

        // 计算校验码 (只计算地址、功能码、字节数和有效数据)
        const calculatedCrc = this.calculateCRC(data.slice(0, 3 + byteCount));

        // 验证CRC
        if (receivedCrc !== calculatedCrc) {
            console.error(`CRC校验失败, 接收: ${receivedCrc.toString(16)}, 计算: ${calculatedCrc.toString(16)}`);
            return null;
        }

        // 确定命令类型
        let commandType = null;
        if (address === 0x01 && functionCode === 0x03) {
            commandType = CommandType.TEMPERATURE;
        } else if (address === 0x03 && functionCode === 0x03) {
            commandType = CommandType.OUT_TEMPERATURE;
        } else if (address === 0x02 && functionCode === 0x03) {
            commandType = CommandType.AIR_QUALITY;
        } else if (address === 0x04 && functionCode === 0x05) {
            commandType = CommandType.AC_CONTROL;
        }

        // 解析结果
        const result = {
            format: 'MODBUS',
            address: address,
            functionCode: functionCode,
            byteCount: byteCount,
            payload: Array.from(payload),
            crc: receivedCrc,
            commandType: commandType,
            rawData: Array.from(data)
        };

        // 根据命令类型解析特定数据
        if (commandType) {
            result.parsedData = this.parseDataByCommandType(commandType, payload);
        }

        return result;
    }

    /**
     * 根据命令类型解析特定数据
     * @param {string} commandType - 命令类型
     * @param {Uint8Array} payload - 有效数据
     * @returns {Object} - 解析后的数据
     */
    parseDataByCommandType(commandType, payload) {
        try {
            switch (commandType) {
                case CommandType.TEMPERATURE:
                    // 使用提供的温湿度解析算法
                    return this.parseTemperatureHumidityData(payload);

                case CommandType.OUT_TEMPERATURE:
                    // 室外温湿度也使用相同的解析算法
                    return this.parseTemperatureHumidityData(payload);

                case CommandType.AIR_QUALITY:
                    // 使用提供的空气质量解析算法
                    return this.parseAirQualityData(payload);

                case CommandType.AC_CONTROL:
                    // 空调控制反馈
                    return {
                        status: 'success',
                        action: payload[0] === 0xFF ? 'on' : 'off'
                    };

                case CommandType.LIGHT_CONTROL:
                    // 灯光控制状态
                    return {
                        status: payload[0] === 0x01 ? 'on' : 'off'
                    };

                case CommandType.HEAT_CONTROL:
                    // 加热控制状态
                    return {
                        status: payload[0] === 0x02 ? 'on' : 'off'
                    };

                case CommandType.DEHUMIDIFY_CONTROL:
                    // 除湿控制状态
                    return {
                        status: payload[0] === 0x04 ? 'on' : 'off'
                    };

                case CommandType.ALARM_LIGHT_CONTROL:
                    // 报警灯控制状态
                    return {
                        status: payload[0] === 0x08 ? 'on' : 'off'
                    };

                case CommandType.SMOKE_SENSOR:
                    // 烟感状态
                    return {
                        hasAlarm: payload[0] === 0x01,
                        status: payload[0] === 0x01 ? '有报警' : '无报警'
                    };

                default:
                    return {raw: Array.from(payload)};
            }
        } catch (error) {
            console.error(`解析数据异常[${commandType}]:`, error);
            return {
                raw: Array.from(payload),
                error: error.message
            };
        }
    }
}